package itu.dk.bosk.ex9;

import java.sql.SQLException;
import java.util.Random;

public class Main {

	public static void main(String[] args) {

		// Create a single person
		Person p = new Person(5, "Ole", "Jensen");
		System.out.println("Created the person: " + p);

		// Test if we can save a person to DB
		try {
			DbDataAccessObject.savePerson(p);
			System.out.println("Saved the person: " + p);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Failed to save person");
			System.exit(1);
		}

		// Test if we can load a person from DB
		try {
			Person personFromDb = DbDataAccessObject.loadPerson(5);
			System.out.println("Loaded the person: " + personFromDb);
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println("Failed to load person");
			System.exit(1);
		}

                // Test if prepared statements are faster for INSERTS and SELECTS..
                // Test execution time for inserts with normal statements:

                //Clear database and build again..
                DbDataAccessObject.dropTable();
                DbDataAccessObject.createTable();

		double time = System.currentTimeMillis();

		for (int i=0;i<1000;i++) {
			String firstname = getRandomString();
			String lastname = getRandomString();

			try {
				DbDataAccessObject.savePerson(new Person(i,firstname,lastname));
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Normal statement insert: " + (System.currentTimeMillis()-time));

                //Select with normal statments
                time = System.currentTimeMillis();
                for (int i=0;i<1000;i++) {
                    try{
                        DbDataAccessObject.loadPerson(i);
                    }catch(SQLException ex){
                        System.out.println("Normal statement, load person ERROR!");
                    }
                }
                System.out.println("Normal statement select: " + (System.currentTimeMillis()-time));



                //Test insert  with prepared statement

                //Clear database and build again..
                DbDataAccessObject.dropTable();
                DbDataAccessObject.createTable();

		time = System.currentTimeMillis();

		for (int i=0;i<1000;i++) {
			String firstname = getRandomString();
			String lastname = getRandomString();

			try {
				DbDataAccessObject.savePersonPrepared(new Person(i,firstname,lastname));
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		System.out.println("PreparedStatement insert: " + (System.currentTimeMillis()-time));

                //Select with prepared statments
                time = System.currentTimeMillis();
                for (int i=0;i<1000;i++) {
                    try{
                        DbDataAccessObject.loadPersonPrepared(i);
                    }catch(SQLException ex){
                        System.out.println("Prepared statement, load person ERROR!");
                    }
                }
                System.out.println("Prepared statement select: " + (System.currentTimeMillis()-time));

                /*
                 * Ex 9.4.1
                 * On our system, we get these results (in milliseconds):
                 * Normal statement insert: 3416.0
                 * Normal statement select: 3058.0
                 * PreparedStatement insert: 359.0
                 * Prepared statement select: 94.0
                 *
                 * These results clearly show that PreparedStatements are faster,
                 * when executing many, similair queries. This also makes good since,
                 * since the driver can prepare the statement once (in our implementation,
                 * this happens in the top static-block of our DAO, and in constant time).
                 * Therefore, the prepared statement example can execute the queries a
                 * whole lot faster.
                 *
                 * It also shows that inserts are a lot slower than selects, but that
                 * what really takes the most time, is preparing the statements.
                 *
                 * Ex 9.4.2
                 * We would make queries that are so different that each call
                 * would require the creation of a new prepared statement..
                 */
	}

        public static String getRandomString() {

		 Random r = new Random();
		 String token = Long.toString(Math.abs(r.nextLong()), 36);
		 return token;
	}
}
